using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using UnityEngine.Profiling;

public class MaterialScannerWindow : EditorWindow
{
    private List<MaterialInfo> normalMaterialInfos = new List<MaterialInfo>();
    private List<MaterialInfo> hiddenMaterialInfos = new List<MaterialInfo>();
    private HashSet<string> previousScanMaterialKeys = new HashSet<string>(); // 上一次扫描的材质球标识
    private string savePath = "Assets/MaterialsInfo.csv";
    private string previousScanPath = "Assets/PreviousScan.json"; // 保存上一次扫描结果的路径
    private Dictionary<Material, string> prefabCache = new Dictionary<Material, string>();
    private Vector2 scrollPositionNormal;
    private Vector2 scrollPositionHidden;
    private long totalNormalMemorySize = 0;
    private long totalHiddenMemorySize = 0;
    private bool removeDuplicates = true; // 去重开关

    [MenuItem("HRP/Material Scanner")]
    public static void ShowWindow()
    {
        GetWindow<MaterialScannerWindow>("Material Scanner");
    }

    private void OnGUI()
    {
        GUILayout.Label("Material Scanner", EditorStyles.boldLabel);

        removeDuplicates = EditorGUILayout.Toggle("Remove Duplicates", removeDuplicates);

        if (GUILayout.Button("Scan Materials"))
        {
            ScanMaterials();
        }

        if (GUILayout.Button("Clear Results"))
        {
            ClearResults();
        }

        if (GUILayout.Button("Clear Normal Materials From Memory"))
        {
            if (EditorUtility.DisplayDialog("Warning", "This will clear all normal materials from memory in editor mode. This action cannot be undone. Are you sure you want to proceed?", "Yes", "No"))
            {
                ClearNormalMaterialsFromMemory();
            }
        }

        GUILayout.Space(10);

        if (normalMaterialInfos.Count > 0 || hiddenMaterialInfos.Count > 0)
        {
            if (GUILayout.Button("Save to CSV"))
            {
                SaveToCSV();
            }
        }

        GUILayout.Label("Save Path:", EditorStyles.label);

        // 文件保存路径选择对话框
        if (GUILayout.Button("Select Save Path"))
        {
            savePath = EditorUtility.SaveFilePanel("Save Material Info", "", "MaterialsInfo.csv", "csv");
        }
        GUILayout.Label(savePath, EditorStyles.wordWrappedLabel);

        if (normalMaterialInfos.Count > 0 || hiddenMaterialInfos.Count > 0)
        {
            GUILayout.Space(10);

            // 显示正常材质球的结果和总内存大小
            GUILayout.Label($"Normal Materials: {normalMaterialInfos.Count} (Total Size: {totalNormalMemorySize} KB)", EditorStyles.boldLabel);
            scrollPositionNormal = EditorGUILayout.BeginScrollView(scrollPositionNormal, GUILayout.Height(400));
            foreach (var info in normalMaterialInfos)
            {
                GUILayout.Label($"Material: {info.MaterialName}, Shader: {info.ShaderName}, Size: {info.MaterialSize} KB, Referenced By: {info.PrefabName}");
            }
            EditorGUILayout.EndScrollView();

            GUILayout.Space(10);

            // 显示隐藏材质球的结果和总内存大小
            GUILayout.Label($"Hidden Materials: {hiddenMaterialInfos.Count} (Total Size: {totalHiddenMemorySize} KB)", EditorStyles.boldLabel);
            scrollPositionHidden = EditorGUILayout.BeginScrollView(scrollPositionHidden, GUILayout.Height(400));
            foreach (var info in hiddenMaterialInfos)
            {
                GUILayout.Label($"Material: {info.MaterialName}, Shader: {info.ShaderName}, Size: {info.MaterialSize} KB, Referenced By: {info.PrefabName}");
            }
            EditorGUILayout.EndScrollView();
        }
    }

    private void ScanMaterials()
    {
        ClearResults(); // 开始扫描前清空结果

        // 加载上一次的扫描结果
        LoadPreviousScan();

        Material[] allMaterials = Resources.FindObjectsOfTypeAll<Material>();
        int materialCount = allMaterials.Length;

        HashSet<string> processedMaterials = new HashSet<string>(); // 用于去重

        for (int i = 0; i < materialCount; i++)
        {
            Material mat = allMaterials[i];

            if (mat == null) continue; // 确保材质不为null

            // 获取材质球文件路径和名称用于去重
            string materialPath = AssetDatabase.GetAssetPath(mat);
            string materialKey = $"{mat.name}_{materialPath}";

            if (removeDuplicates && processedMaterials.Contains(materialKey))
            {
                continue; // 已经处理过的材质球，跳过
            }
            processedMaterials.Add(materialKey);

            long size = Profiler.GetRuntimeMemorySizeLong(mat) / 1024; // Size in KB

            // 获取材质球文件名称
            string materialName = mat.name;

            // 获取Shader名称
            string shaderName = mat.shader != null ? mat.shader.name : "N/A";

            string referencedBy = FindPrefabOrGameObjectName(mat);

            var materialInfo = new MaterialInfo(materialName, shaderName, size, referencedBy, materialPath);

            // 判断是否是隐藏材质或渲染管线材质
            if (mat.hideFlags != HideFlags.None || mat.name.StartsWith("Hidden/"))
            {
                hiddenMaterialInfos.Add(materialInfo);
                totalHiddenMemorySize += size;
            }
            else
            {
                // 检查是否为新增材质球
                if (!previousScanMaterialKeys.Contains(materialKey))
                {
                    materialInfo.IsNew = true;
                }

                normalMaterialInfos.Add(materialInfo);
                totalNormalMemorySize += size;
            }

            // 更新进度条
            EditorUtility.DisplayProgressBar("Scanning Materials", $"Processing {i + 1} of {materialCount} materials...", (float)(i + 1) / materialCount);
        }

        // 关闭进度条
        EditorUtility.ClearProgressBar();

        // 保存当前扫描结果，以便下次扫描时比较
        SaveCurrentScan(processedMaterials);

        Debug.Log("Material scan completed.");
    }

    private string FindPrefabOrGameObjectName(Material material)
    {
        GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();

        foreach (GameObject go in allObjects)
        {
            Renderer renderer = go.GetComponent<Renderer>();
            if (renderer != null && renderer.sharedMaterial == material)
            {
                // 尝试获取预制体路径
                string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);
                if (!string.IsNullOrEmpty(assetPath))
                {
                    return Path.GetFileNameWithoutExtension(assetPath);
                }
                else
                {
                    // 如果不是预制体，返回引用该材质球的GameObject的名称
                    return go.name;
                }
            }
        }
        return "N/A"; // 如果未找到任何引用对象，则返回 "N/A"
    }

    private void ClearResults()
    {
        normalMaterialInfos.Clear();
        hiddenMaterialInfos.Clear();
        totalNormalMemorySize = 0;
        totalHiddenMemorySize = 0;
        Debug.Log("Material scan results cleared.");
    }

    private void ClearNormalMaterialsFromMemory()
    {
        // 首先，手动卸载那些正常的材质球（不是隐藏材质球）
        Material[] allMaterials = Resources.FindObjectsOfTypeAll<Material>();

        foreach (Material mat in allMaterials)
        {
            if (mat != null && mat.hideFlags == HideFlags.None && !mat.name.StartsWith("Hidden/"))
            {
                Resources.UnloadAsset(mat);
            }
        }

        // 然后，调用 Resources.UnloadUnusedAssets 来释放内存
        Resources.UnloadUnusedAssets();

        Debug.Log("Normal materials unloaded from memory in editor mode.");
    }

    private void SaveToCSV()
    {
        if (string.IsNullOrEmpty(savePath))
        {
            Debug.LogError("Save path is not set or invalid.");
            return;
        }

        try
        {
            using (StreamWriter writer = new StreamWriter(savePath))
            {
                writer.WriteLine("Category,Material Name,Shader Name,Size (KB),Referenced By,File Path,Is New");

                // 保存正常材质球信息
                foreach (var info in normalMaterialInfos)
                {
                    string isNew = info.IsNew ? "New" : "";
                    writer.WriteLine($"Normal,{info.MaterialName},{info.ShaderName},{info.MaterialSize},{info.PrefabName},{info.FilePath},{isNew}");
                }

                // 保存隐藏材质球信息
                foreach (var info in hiddenMaterialInfos)
                {
                    writer.WriteLine($"Hidden,{info.MaterialName},{info.ShaderName},{info.MaterialSize},{info.PrefabName},{info.FilePath},");
                }
            }

            AssetDatabase.Refresh();
            Debug.Log($"Material information saved to {savePath}");
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"Failed to save CSV: {ex.Message}");
        }
    }

    private void SaveCurrentScan(HashSet<string> processedMaterials)
    {
        File.WriteAllText(previousScanPath, JsonUtility.ToJson(new ScanData { MaterialKeys = new List<string>(processedMaterials) }));
    }

    private void LoadPreviousScan()
    {
        if (File.Exists(previousScanPath))
        {
            var scanData = JsonUtility.FromJson<ScanData>(File.ReadAllText(previousScanPath));
            previousScanMaterialKeys = new HashSet<string>(scanData.MaterialKeys);
        }
    }

    [System.Serializable]
    private class ScanData
    {
        public List<string> MaterialKeys;
    }

    private class MaterialInfo
    {
        public string MaterialName;
        public string ShaderName;
        public long MaterialSize;
        public string PrefabName;  // 这里表示的是引用该材质球的预制体名称或对象名称
        public string FilePath;
        public bool IsNew = false;  // 标记材质球是否为新增

        public MaterialInfo(string materialName, string shaderName, long materialSize, string prefabName, string filePath)
        {
            MaterialName = materialName;
            ShaderName = shaderName;
            MaterialSize = materialSize;
            PrefabName = prefabName;
            FilePath = filePath;
        }
    }
}
